home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / DDJMAG / DDJ9207.ZIP / AVKCAPT.ZIP / ACAVK.C next >
C/C++ Source or Header  |  1992-04-03  |  28KB  |  1,069 lines

  1. //-------------------------------------------------------------------------
  2. //            ActionMedia II Programmer's Toolkit
  3. //            
  4. //            Windows Motion Capture Sample Program
  5. //
  6. // Application:    AvkCapt.exe
  7. // Module Name:    acavk.c
  8. //
  9. // description:    this module contains the functions that directly reference
  10. //        AVK API functions.
  11. //
  12. // Copyright Intel Corp. 1991, 1992
  13. // All Rights Reserved.
  14. //
  15. //-------------------------------------------------------------------------
  16. //
  17. // Exported functions from this module:
  18. //
  19. //        InitAvk
  20. //        EndAvk
  21. //        ToggleMonitor
  22. //        GetDevCaps
  23. //        SetDstBox
  24. //        ToState
  25. //        IsState
  26. //        GetState
  27. //
  28. //-------------------------------------------------------------------------
  29. //
  30. //    Functions local to this module:
  31. //    
  32. //        CreateCaptureGroup
  33. //        CreateVideoStream
  34. //        CreateAudioStream
  35. //        LoadVshFile
  36. //        MonitorOn
  37. //        MonitorOff
  38. //        CreateView
  39. //    
  40. //-------------------------------------------------------------------------
  41.  
  42. #include <windows.h>
  43. #include <stdio.h>
  44. #include <io.h>
  45. #include <memory.h>
  46. #include "avkapi.h"
  47. #include "avkio.h"    // AVSS file I/O subsystem header
  48. #define  ACAVK_NOEXTERNS 1
  49. #include "avkcapt.h"    // main application header
  50. #include "disperr.h"    // error display subsystem header
  51. #include "memalloc.h"    // memory allocation subsystem header
  52. #include "log.h"
  53. #include "copylist.h"
  54.  
  55. extern HWND        hwndMain;
  56. extern HANDLE        hInst;
  57. extern VIDEO_SYNC    Syncs[];
  58.  
  59. //-------------------------------------------------------------------------
  60. //    Local variables.
  61. //-------------------------------------------------------------------------
  62.  
  63. static WORD    State = ST_UNINITIALIZED;    // current state of
  64.                         // capture engine
  65. VIEW        View;                // view control structure
  66. AVIO_SUM_HDR    Avio;                // master control struct
  67.                         // for AVSS file I/O
  68. I16        AvkRet;                // general AVK return
  69.                         // code variable
  70. WORD        CaptureSync = SYNC_NTSC;    // default to NTSC 
  71. char far    *pVshBuf = NULL;        // buffer for reading VSH data
  72. U32        VshSize;            // size of the VSH data.
  73. CAPT        Vid;                // video capture
  74.                         // control structure
  75. CAPT        Aud;                // audio capture
  76.                         // control structure
  77.  
  78. //-------------------------------------------------------------------------
  79. //    Variables for the clipping timer.
  80. //-------------------------------------------------------------------------
  81.  
  82. FARPROC        lpThunk;        // instance 'thunk' for
  83.                     // clip timer proc
  84. BOOL        bClipTimerSet = FALSE;    // TRUE when clip timer running
  85. COPYLIST    CopyList;
  86.  
  87. //-------------------------------------------------------------------------
  88. //    RTV 2.0 encoding arguments.  Used to encode captured video into
  89. //    AVSS Real-Time Video 2.0 compressed format.  Note that the values
  90. //
  91. //-------------------------------------------------------------------------
  92.  
  93. AVK_RTV_20_ENCODE_ARGS Rtv20Args = {
  94.     12,                    // arg count
  95.     AVK_RTV_2_0,                 // alg size
  96.     0,0,                    // x,y coords of origin
  97.     128, 240,                // xLen, yLen - fill in 
  98.     3,                     // still period
  99.     0, 0,                    // Bytes,lines
  100.     AVK_RTV_20_PREFILTER | AVK_RTV_20_ASPECT_25,     // flags
  101.     0, 0                    // quant values
  102. };
  103.  
  104. //-------------------------------------------------------------------------
  105. //    AVK handles.
  106. //-------------------------------------------------------------------------
  107.  
  108. HAVK    hAvk        = (HAVK)0;
  109. HAVK    hDev        = (HAVK)0;
  110. HAVK    hGrp        = (HAVK)0;
  111.  
  112. //-------------------------------------------------------------------------
  113. //    Local function prototypes.
  114. //-------------------------------------------------------------------------
  115.  
  116. static BOOL    CreateCaptureGroup(VOID);
  117. static BOOL    CreateVideoStream(VOID);
  118. static BOOL    CreateAudioStream(VOID);
  119. static BOOL    CreateView(VIEW *);
  120. static BOOL    LoadVshFile(VOID);
  121. static BOOL    MonitorOn(VOID);    
  122. static BOOL    MonitorOff(VOID);    
  123. BOOL        GetDevCaps(VIEW *);
  124. BOOL        SetDstBox(HWND);
  125. WORD        ToState(WORD);
  126. BOOL        IsState(WORD);
  127. WORD        GetState(VOID);
  128. VOID        SetClipTimer(VOID);
  129. VOID        KillClipTimer(VOID);
  130. WORD FAR PASCAL    ClipTimerProc(HWND, WORD, WORD, LONG);
  131.  
  132. //-------------------------------------------------------------------------
  133. //FUNCTION:
  134. //    
  135. //    BOOL InitAvk(VOID)
  136. //
  137. //DESCRIPTION:
  138. //
  139. //    Create an AVK session and open the board.  After determining the
  140. //    type of monitor we have, and creating a view, we create a 
  141. //    capture group with all of its resources and an image we will use to
  142. //    grab a frame from the capture group while we are premonitoring.
  143. //
  144. //RETURN:
  145. //    
  146. //    TRUE on success.
  147. //    FALSE on any error (error message box is displayed before exit).
  148. //     
  149. //-------------------------------------------------------------------------
  150.  
  151. BOOL
  152. InitAvk()
  153. {
  154.     // Don't do if already initialized.
  155.  
  156.     if (!IsState(ST_UNINITIALIZED))
  157.         return TRUE;
  158.  
  159.     // Start an AVK session with messaging.  Give AVK the
  160.     // client window handle for returning messages.
  161.  
  162.     if ((AvkRet = AvkBeginMsg(hwndMain, &hAvk, AVK_SESSION_DEFAULT)) != OK)
  163.         return DispAvkErr(AvkRet, "AvkBeginMsg");
  164.  
  165.     // Now that we have our AVK session handle, we can initialize the
  166.     // error display system and give it the AVK handle. Be sure to
  167.     // turn on date and time flags and logging to disk.
  168.  
  169.     InitErrSystem(hAvk, TRUE, TRUE, TRUE);
  170.  
  171.     // Open the device (board).
  172.     
  173.     if ((AvkRet = AvkDeviceOpen(hAvk, 0, AVK_DEV_OPEN_EXCLUSIVE, &hDev)) 
  174.             != OK)
  175.         return DispAvkErr(AvkRet, "AvkDeviceOpen");
  176.  
  177.     // Lastly, get the capture sync by calling AvkDeviceVideoIn().  The
  178.     // capture sync will be returned as part of the 32-bit parameter
  179.     // for the AVK_IDENTIFY message.  We will have to suspend our 
  180.     // initialization for the time being and return to the message loop
  181.     // to await an AVK_IDENTIFY message with the capture sync value.
  182.     // From there, we will call CreateAvkResources() to finish 
  183.     // initializing AVK for capture.
  184.  
  185.     if ((AvkRet = AvkDeviceVideoIn(hDev, AVK_CONN_DIGITIZER)) != OK)
  186.         return DispAvkErr(AvkRet, "AvkDeviceVideoIn");
  187.  
  188.     return TRUE;
  189. }
  190.  
  191. //-------------------------------------------------------------------------
  192. //FUNCTION:
  193. //    
  194. //    BOOL CreateAvkResources(WORD NewCaptureSync)
  195. //
  196. //DESCRIPTION:
  197. //    
  198. //RETURN:
  199. //     
  200. //-------------------------------------------------------------------------
  201.  
  202. BOOL
  203. CreateAvkResources(WORD NewCaptureSync)
  204. {
  205.     // We called AvkDeviceVideoIn() to produce an AVK_IDENTIFY
  206.     // message.  On receipt of the AVK_IDENTIFY message, we extracted
  207.     // the source sync and then called CreateAvkResources() to finish
  208.     // initializing AVK. Set the CaptureSync variable accordingly.
  209.  
  210.     switch (NewCaptureSync)
  211.     {
  212.         case AVK_SYNC_NTSC:    CaptureSync = SYNC_NTSC;    break;
  213.         case AVK_SYNC_PAL:    CaptureSync = SYNC_PAL;        break;
  214.     }
  215.  
  216.     // Once the device has been opened, we can get the AVK device
  217.     // capabilities from AVK.INI
  218.  
  219.     if (!GetDevCaps(&View))
  220.         return FALSE;
  221.  
  222.     // Now that we have figured out the AVK screen resolution and the
  223.     // Windows->AVK conversion factors, let's set the stream 
  224.     // destination coordinates.
  225.  
  226.     // Create the AVK view.
  227.  
  228.     if (!CreateView(&View))
  229.          return FALSE;
  230.  
  231.     // Load the VSH file.  This file contains data used in compressing
  232.     // the incoming motion into an RTV 2.0 file.
  233.  
  234.     if (!LoadVshFile())
  235.         return FALSE;
  236.  
  237.     // Create a capture group.
  238.  
  239.     if (!CreateCaptureGroup())
  240.         return FALSE;
  241.  
  242.     // Set the initialization flag.
  243.  
  244.     ToState(ST_INITIALIZED);
  245.  
  246.     return TRUE;
  247. }
  248.  
  249. //-------------------------------------------------------------------------
  250. //FUNCTION:
  251. //    
  252. //    BOOL EndAvk(VOID)
  253. //
  254. //DESCRIPTION:
  255. //
  256. //    Close an AVK session by calling AvkEnd().  This also
  257. //    implicitly destroys all created objects.
  258. //    
  259. //RETURN:
  260. //    
  261. //    TRUE on success.
  262. //    FALSE on any error (error message box is displayed before exit).
  263. //     
  264. //-------------------------------------------------------------------------
  265.  
  266. BOOL
  267. EndAvk()
  268. {
  269.     BOOL    Ret = TRUE;
  270.  
  271.     // End the session.
  272.  
  273.     if (hAvk != HNULL)
  274.     {
  275.         if ((AvkRet = AvkEnd(hAvk)) != OK)
  276.         {
  277.             DispAvkErr(AvkRet, "AvkEnd");
  278.             Ret = FALSE;
  279.         }
  280.     }
  281.  
  282.     if (Vid.pBufHead)
  283.     {
  284.         MemFree(Vid.pBufHead);
  285.         Vid.pBufHead = NULL;
  286.     }
  287.     if (Aud.pBufHead)
  288.     {
  289.         MemFree(Aud.pBufHead);
  290.         Aud.pBufHead = NULL;
  291.     }
  292.  
  293.     // Null out all of the AVK handles.
  294.  
  295.     hAvk = hDev = HNULL;
  296.     hGrp = HNULL;
  297.     Vid.hGrpBuf = Vid.hStrm = HNULL;
  298.     Aud.hGrpBuf = Aud.hStrm = HNULL;
  299.     View.hView = HNULL;
  300.     View.hConnDigi2Strm = View.hConnStrm2View = HNULL;
  301.  
  302.     ToState(ST_UNINITIALIZED);
  303.  
  304.     return Ret;
  305. }
  306.  
  307. //-------------------------------------------------------------------------
  308. //FUNCTION:
  309. //    
  310. //    BOOL CreateCaptureGroup(VOID)
  311. //    
  312. //DESCRIPTION:
  313. //
  314. //    Create a Capture Group and all needed resources for premonitoring.
  315. //    In order to capture or premonitor video and/or audio from the digi-
  316. //    tizer, you must create a Group, at least one Group Buffer and 
  317. //    a Video Stream and/or an Audio Stream as needed.  The streams then
  318. //    must be formatted with the information on resolution, bitmap format,
  319. //    capture frame rate, VSH compression data, etc.
  320. //
  321. //    Since the aim of this application is to grab a still image from the
  322. //    video stream, we only create and format a Video Stream here.
  323. //    
  324. //RETURN:
  325. //
  326. //    TRUE on success.
  327. //    FALSE if an AVK call failed.    
  328. //    
  329. //-------------------------------------------------------------------------
  330.  
  331. static BOOL
  332. CreateCaptureGroup()
  333. {
  334.     // Create the capture group.
  335.  
  336.     if ((AvkRet = AvkGrpCreate(hDev, &hGrp)) != OK)
  337.         return DispAvkErr(AvkRet, "AvkGrpCreate");
  338.  
  339.     // Create the group video and audio buffers.
  340.  
  341.     if ((AvkRet = AvkGrpBufCreate(hGrp, AVK_BUF_CAPTURE, VID_BUF_SIZE, 
  342.             VID_BUF_GRAN, 1, &Vid.hGrpBuf)) != OK)
  343.         return DispAvkErr(AvkRet, "AvkGrpBufCreate");
  344.  
  345.     if ((AvkRet = AvkGrpBufCreate(hGrp, AVK_BUF_CAPTURE, AUD_BUF_SIZE, 
  346.             AUD_BUF_GRAN, 1, &Aud.hGrpBuf)) != OK)
  347.         return DispAvkErr(AvkRet, "AvkGrpBufCreate");
  348.  
  349.     // Create host RAM I/O buffers for retrieving video and audio frames.
  350.     
  351.     if ((Vid.pBufHead = MemAlloc(HOST_BUF_SIZE)) == NULL
  352.      || (Aud.pBufHead = MemAlloc(HOST_BUF_SIZE)) == NULL)
  353.         return DispErr("CreateCaptureGroup", 
  354.           "Unable to allocate host RAM I/O buffer");
  355.  
  356.     // Neither has been written to yet.
  357.  
  358.     Vid.BufDataCnt = (U32)0;
  359.     Aud.BufDataCnt = (U32)0;
  360.  
  361.     // Create the video stream.
  362.  
  363.     if (!CreateVideoStream())
  364.         return FALSE;
  365.  
  366.     // Create the audio stream.
  367.  
  368.     if (!CreateAudioStream())
  369.         return FALSE;
  370.  
  371.     // Flush the group to allocate all of the group and stream resources.
  372.  
  373.     if ((AvkRet = AvkGrpFlush(hGrp)) != OK)
  374.         return DispAvkErr(AvkRet, "AvkGrpFlush");
  375.  
  376.     return TRUE;
  377. }
  378.  
  379. //-------------------------------------------------------------------------
  380. //FUNCTION:
  381. //    
  382. //    BOOL CreateVideoStream(VOID)
  383. //
  384. //DESCRIPTION:
  385. //
  386. //    Create and format a video stream for the capture group's video
  387. //    capture buffer.
  388. //    
  389. //RETURN:
  390. //    
  391. //    TRUE on success.
  392. //    FALSE on any error (error message box is displayed before exit).
  393. //     
  394. //-------------------------------------------------------------------------
  395.  
  396. static BOOL
  397. CreateVideoStream()
  398. {
  399.     // Create the video stream.
  400.  
  401.     if ((AvkRet = AvkVidStrmCreate(Vid.hGrpBuf, 0, &Vid.hStrm)) != OK)
  402.         return DispAvkErr(AvkRet, "AvkVidStrmCreate");
  403.  
  404.     // Format the video stream.
  405.     
  406.     Rtv20Args.xLen = Syncs[CaptureSync].xResRTV;
  407.     Rtv20Args.yLen = Syncs[CaptureSync].yResVid;
  408.  
  409.     if ((AvkRet = AvkVidStrmFormat(Vid.hStrm, 
  410.             6, 
  411.             Syncs[CaptureSync].xResVid,
  412.             Syncs[CaptureSync].yResVid,
  413.             AVK_YUV9, 
  414.             Syncs[CaptureSync].FrameRate,
  415.             AVK_RTV_2_0, 
  416.             &Rtv20Args, sizeof(Rtv20Args), sizeof(Rtv20Args),
  417.             pVshBuf, VshSize, 64L * 1024L)) != OK)
  418.         return DispAvkErr(AvkRet, "AvkVidStrmFormat");
  419.  
  420.  
  421.     // Free the VSH buffer now that we don't need it any more - 
  422.     // AvkVidStrmFormat() makes a copy of the VSH data.
  423.  
  424.     MemFree(pVshBuf);
  425.  
  426.     // Create the connectors from the digitizer to the video stream. 
  427.     // When this connector is enabled, capture data will begin to
  428.     // flow from the CS2 board to the stream.
  429.  
  430.     if ((AvkRet = AvkConnCreate(AVK_CONN_DIGITIZER, NULL, Vid.hStrm,
  431.       NULL, 0, &View.hConnDigi2Strm)) != OK)
  432.           return DispAvkErr(AvkRet,
  433.             "AvkConnCreate (Digitizer to Stream)");
  434.  
  435.     // Create the connector from the video stream to the view.  When 
  436.     // this connector is enabled, the captured data will begin to 
  437.     // flow from the video stream to the view and, if the view is
  438.     // also enabled, appear on the screen in the rectangle defined
  439.     // in View.DstBox.
  440.  
  441.     if ((AvkRet = AvkConnCreate(Vid.hStrm, NULL, View.hView, 
  442.       &View.DstBox, AVK_PRE_MONITOR, &View.hConnStrm2View)) != OK)
  443.           return DispAvkErr(AvkRet, "AvkConnCreate (Stream to View)");
  444.  
  445.     return TRUE;
  446. }
  447.  
  448. //-------------------------------------------------------------------------
  449. //FUNCTION:
  450. //    
  451. //    BOOL CreateAudioStream(VOID)
  452. //
  453. //DESCRIPTION:
  454. //
  455. //    Create and format a audio stream for the capture group's audio
  456. //    capture buffer.
  457. //    
  458. //RETURN:
  459. //    
  460. //    TRUE on success.
  461. //    FALSE on any error (error message box is displayed before exit).
  462. //     
  463. //-------------------------------------------------------------------------
  464.  
  465. static BOOL
  466. CreateAudioStream()
  467. {
  468.     // Create an audio stream.
  469.  
  470.     if ((AvkRet = AvkAudStrmCreate(Aud.hGrpBuf, 0, &Aud.hStrm)) != OK)
  471.         return DispAvkErr(AvkRet, "AvkAudStrmCreate");
  472.  
  473.     // Format the audio stream.
  474.  
  475.     if ((AvkRet = AvkAudStrmFormat(Aud.hStrm, FRAME_RATE, AUD_SAMPLE_RATE,
  476.       AVK_ADPCM4, AVK_AUD_MIX, NULL, 0, 0)) != OK)
  477.           return DispAvkErr(AvkRet, "AvkAudStrmFormat");
  478.  
  479.     // Note that setting audio volume has no effect on a capture stream
  480.     // (unless you are also playing back a separate file and want to hear 
  481.     // both the capture and playback audio together).
  482.  
  483.     return TRUE;
  484. }
  485.  
  486. //-------------------------------------------------------------------------
  487. //FUNCTION:                                 
  488. //    
  489. //    BOOL LoadVshFile()
  490. //
  491. //DESCRIPTION:
  492. //
  493. //    Open the standard VSH file that comes with AVK, allocate a block of 
  494. //    memory to hold it and read it in.
  495. //    
  496. //RETURN:
  497. //
  498. //    TRUE on success.
  499. //    FALSE on error (error messages displayed in this function).
  500. //    
  501. //-------------------------------------------------------------------------
  502.  
  503. static BOOL
  504. LoadVshFile()
  505. {
  506.     int            fhVsh;
  507.     OFSTRUCT    Of;
  508.  
  509.     // Open the VSH file. OpenFile will check all directories in the
  510.     // PATH environment variable.
  511.  
  512.     if ((fhVsh = OpenFile(VSHFILE_NAME, &Of, OF_READ)) == -1)
  513.         return DispErr("LoadVshFile",
  514.             "Unable to find the file KE080200.VSH");
  515.     
  516.     VshSize = filelength(fhVsh);
  517.  
  518.     // Range check - we don't want to try to read 0 bytes or a file
  519.     // greater than _lread can handle.  Reject if VshSize == 0 or
  520.     // VshSize > 65535L.
  521.  
  522.     if (!VshSize || VshSize & 0xffff0000)
  523.         return DispErr("LoadVshFile", "VSH file too large to load");
  524.  
  525.     // Allocate a buffer to stash the VSH file.
  526.  
  527.     if ((pVshBuf = MemAlloc((WORD)VshSize)) == NULL)
  528.         return DispErr("LoadVshFile",
  529.             "Unable to allocate VSH file buffer");
  530.  
  531.     // Read the VSH data from the file.
  532.  
  533.     if (_lread(fhVsh, pVshBuf, (WORD)VshSize) != (WORD)VshSize)
  534.         return DispErr("LoadVshFile", "Unable to read VSH file");
  535.  
  536.     return TRUE;
  537. }
  538.  
  539. //-------------------------------------------------------------------------
  540. //FUNCTION:
  541. //    
  542. //    BOOL    ToggleMonitor(VOID)
  543. //
  544. //DESCRIPTION:
  545. //
  546. //    If we are initialized and monitoring is off, turn it on.  If 
  547. //    monitoring is on and we are not capturing, turn it off.    We call
  548. //    the functions MonitorOn() and MonitorOff() to do the real work.
  549. //    
  550. //RETURN:
  551. //    
  552. //    AVK_ERR_OK (0) on success.
  553. //    Non-zero on AVK error returned from MonitorOn() or MonitorOff
  554. //     
  555. //-------------------------------------------------------------------------
  556.  
  557. BOOL
  558. ToggleMonitor()
  559. {
  560.     BOOL    bRet;
  561.     
  562.     // Call MonitorOn() or MonitorOff() according to the current
  563.     // state.  Note that we won't turn off monitoring if the
  564.     // current state is ST_CAPTURING.  Capturing has to be toggled
  565.     // off first.
  566.  
  567.     switch (GetState())
  568.     {
  569.         case ST_INITIALIZED:    bRet = MonitorOn();    break;
  570.         case ST_MONITORING:    bRet = MonitorOff();    break;
  571.         default:        bRet = TRUE;        break;
  572.     }
  573.     return bRet;
  574. }
  575.  
  576. //-------------------------------------------------------------------------
  577. //FUNCTION:
  578. //    
  579. //    BOOL MonitorOn(VOID)
  580. //
  581. //DESCRIPTION:
  582. //
  583. //    Turn on premonitoring. 
  584. //    
  585. //RETURN:
  586. //    
  587. //    TRUE on success.
  588. //    FALSE on any error (error message box is displayed before exit).
  589. //     
  590. //-------------------------------------------------------------------------
  591.  
  592. static BOOL
  593. MonitorOn()
  594. {
  595.     // Enable the connectors from the digitizer to the video stream
  596.     // and from the video stream to the view.  Video will be
  597.     // displayed.
  598.  
  599.     if ((AvkRet = AvkConnEnable(View.hConnDigi2Strm, NOW)) != OK
  600.      || (AvkRet = AvkConnEnable(View.hConnStrm2View, NOW)) != OK)
  601.         return DispAvkErr(AvkRet, "AvkConnEnable");
  602.  
  603.     // Turn on audio.
  604.  
  605.     if ((AvkRet = AvkDeviceAudioIn(hDev, AVK_AUD_CAPT_LINE_INPUT,
  606.       AVK_MONITOR_ON)) != AVK_ERR_OK)
  607.         return DispAvkErr(AvkRet, "AvkDeviceAudioIn");
  608.  
  609.     // State transition to monitoring state.
  610.  
  611.     ToState(ST_MONITORING);
  612.  
  613.     SetClipTimer();
  614.  
  615.      return TRUE;
  616. }
  617.  
  618. //-------------------------------------------------------------------------
  619. //FUNCTION:
  620. //    
  621. //    BOOL MonitorOff(VOID)
  622. //
  623. //DESCRIPTION:
  624. //
  625. //    Turn off premonitoring. 
  626. //    
  627. //RETURN:
  628. //    
  629. //    TRUE on success.
  630. //    FALSE on any error (error message box is displayed before exit).
  631. //     
  632. //-------------------------------------------------------------------------
  633.  
  634. static BOOL
  635. MonitorOff()
  636. {
  637.     KillClipTimer();
  638.  
  639.     // Turn off the flow of video by hiding the connectors.  AvkConnHide()
  640.     // paints the key color (black) into the connector's destination and
  641.     // then disables the connector.
  642.  
  643.     if ((AvkRet = AvkConnHide(View.hConnStrm2View, NOW)) != OK
  644.      || (AvkRet = AvkConnHide(View.hConnDigi2Strm, NOW)) != OK)
  645.         return DispAvkErr(AvkRet, "AvkConnHide");
  646. #if 0
  647.     if ((AvkRet = AvkViewCleanRect(View.hView, &View.DstBox)) != OK)
  648.         return DispAvkErr(AvkRet, "AvkViewCleanRect");
  649. #endif
  650.  
  651.     // Turn off audio monitoring.
  652.  
  653.     if ((AvkRet = AvkDeviceAudioIn(hDev, AVK_AUD_CAPT_LINE_INPUT,
  654.       AVK_MONITOR_OFF)) != AVK_ERR_OK)
  655.         return DispAvkErr(AvkRet, "AvkDeviceAudioIn");
  656.  
  657.     // State transition from monitoring state to initialized state.
  658.     
  659.     ToState(ST_INITIALIZED);
  660.  
  661.      return TRUE;
  662. }
  663.  
  664. //-------------------------------------------------------------------------
  665. //FUNCTION:                                 
  666. //    
  667. //    BOOL GetDevCaps()
  668. //
  669. //DESCRIPTION:
  670. //
  671. //    Get the device capabilities from AVK.  Use the DviMonitorSync value
  672. //    which was extracted from AVK.INI to decide on the AVK View type and
  673. //    the x and y resolutions.  
  674. //    
  675. //RETURN:
  676. //
  677. //    TRUE    on success.
  678. //    FALSE    if AvkGetDevCaps() fails or returns an unrecognized
  679. //        DviMonitorSync.
  680. //    
  681. //-------------------------------------------------------------------------
  682.  
  683. BOOL
  684. GetDevCaps(VIEW *pView)
  685. {
  686.     DVICAPS    DevCaps;
  687.  
  688.     // Get the physical screen resolution from the system.
  689.  
  690.     pView->cxScreen = GetSystemMetrics(SM_CXSCREEN);
  691.     pView->cyScreen = GetSystemMetrics(SM_CYSCREEN);
  692.  
  693.     // Get the AVK device capabilities which were set in AVK.INI
  694.     
  695.     if ((AvkRet = AvkGetDevCaps(0, sizeof(DevCaps), &DevCaps)) != OK)
  696.         return DispAvkErr(AvkRet, "AvkGetDevCaps");
  697.  
  698.     if (DevCaps.DigitizerRevLevel == 0)
  699.         return DispErr("GetDevCaps", 
  700.           "Digitizer needed for capturing - check AVK.INI");
  701.  
  702.     // Interpret DVICAPS data according to our completely arbitrary 
  703.     // precedence.  Since more than one monitor choice can be bitmapped 
  704.     // in DviMonitorSync, we default in whatever order most suits 
  705.     // the specific app's needs.  In this case, we let VGA take 
  706.     // precedence over XGA if both are indicated, and either VGA or
  707.     // XGA over either PAL or NTSC.
  708.  
  709.     if (DevCaps.DviMonitorSync & 0x10)        // VGA
  710.     {
  711.         pView->cxView     = 256;
  712.         pView->cyView     = 240;
  713.         pView->VidType = AVK_VID_VGA_KEYED;
  714.         pView->bIsKeyed = TRUE;
  715.     }
  716.     else if (DevCaps.DviMonitorSync & 0x100)    // XGA
  717.     {
  718.         pView->cxView     =  256;
  719.         pView->cyView     =  192;
  720.         pView->VidType = AVK_VID_XGA_KEYED;
  721.         pView->bIsKeyed = TRUE;
  722.     }
  723.     else if (DevCaps.DviMonitorSync & 0x02)        // PAL
  724.     {
  725.         pView->cxView = 306;
  726.         pView->cyView = 288;
  727.         pView->VidType = AVK_VID_PAL;
  728.     }
  729.     else if (DevCaps.DviMonitorSync & 0x01)        // NTSC
  730.     {
  731.         pView->cxView = 256;
  732.         pView->cyView = 240;
  733.         pView->VidType = AVK_VID_NTSC;
  734.     }
  735.     else
  736.         return DispErr("GetDevCaps", "Invalid monitor sync");
  737.  
  738.     // Calculate Screen-To-AVK coordinate conversion deltas.
  739.     // We will use these deltas to convert from the native screen 
  740.     // resolution to the AVK View resolution. For example, given a
  741.     // screen resolution of 640x489 and an AVK View of 256x240,
  742.     // we convert an X coordinate with the formula:
  743.     //
  744.     //    Xavk = (int)((double)Xscreen * (256.0 / 640.0))
  745.     //
  746.  
  747.     pView->xDelta = (double)pView->cxView / (double)pView->cxScreen;
  748.     pView->yDelta = (double)pView->cyView / (double)pView->cyScreen;
  749.  
  750.     return TRUE;
  751. }
  752.  
  753. //-------------------------------------------------------------------------
  754. //FUNCTION:                                 
  755. //    
  756. //    BOOL CreateView(pView)
  757. //
  758. //PARMS IN:
  759. //    
  760. //    VIEW   *pView;        pointer to View structure    
  761. //    
  762. //DESCRIPTION:
  763. //
  764. //    Create and display an AVK View.  The View describes the motion
  765. //    video plane plane on the motion video monitor.    This view is a 
  766. //    YUV 9-bit view.  The resolution and video type (e.g., VGA, XGA, 
  767. //    etc.) will be determined by the type of motion video monitor sync 
  768. //    specified in the AVK.INI file.  We extracted this information in 
  769. //    the function GetDevCaps(). 
  770. //    
  771. //RETURN:
  772. //
  773. //    TRUE on success.
  774. //    FALSE if an AVK call failed.    
  775. //    
  776. //-------------------------------------------------------------------------
  777.  
  778. static BOOL
  779. CreateView(VIEW *pView)
  780. {
  781.     // Create the View.  
  782.  
  783.     if ((AvkRet = AvkViewCreate(hDev, pView->cxView,
  784.         pView->cyView, AVK_YUV9,  pView->VidType, 
  785.             &pView->hView)) != OK)
  786.           return DispAvkErr(AvkRet, "AvkViewCreate");
  787.  
  788.     // After creating a View, we display the View.  This call actually
  789.     // makes the View visible on the monitor.  The View is initially
  790.     // displayed as a black rectangle.
  791.  
  792.     if ((AvkRet = AvkViewDisplay(hDev, pView->hView, NOW, 
  793.       AVK_VIEW_DISPLAY_DEFAULT)) != OK)
  794.           return DispAvkErr(AvkRet, "AvkViewDisplay");
  795.  
  796.     // Set the destination box for the stream-to-view connector according
  797.     // to the coordinates of the main window's client rectangle.
  798.  
  799.     if (!SetDstBox(hwndMain))
  800.         return FALSE;
  801.  
  802.     return TRUE;
  803. }
  804.  
  805. //-------------------------------------------------------------------------
  806. //FUNCTION:
  807. //    
  808. //    BOOL SetDstBox(hwndMain)
  809. //    
  810. //PARMS IN:
  811. //    
  812. //    HWND hwndMain;            main window handle
  813. //    
  814. //RETURN:
  815. //-------------------------------------------------------------------------
  816.  
  817. BOOL
  818. SetDstBox(HWND hwndMain)
  819. {
  820.     RECT    WinRect;
  821.     BOX    NewDstBox;
  822.  
  823.     GetClientRect(hwndMain, (LPRECT)&WinRect);
  824.     ClientToScreen(hwndMain, (LPPOINT)&WinRect);
  825.     WinRect.right = WinRect.left + (View.cxScreen >> 1) - 1;
  826.     WinRect.bottom = WinRect.top + (View.cyScreen >> 1) -1;
  827.     WinRect2AvkBox(&WinRect, &NewDstBox, &View);
  828.  
  829.     if (View.hConnStrm2View)
  830.     {
  831.         // Hide the connector destination.
  832.  
  833.         if ((AvkRet = AvkConnHide(View.hConnStrm2View, NOW)) != OK)
  834.             return DispAvkErr(AvkRet, "AvkConnHide");
  835.  
  836.         // Clean the old rect's area to black.
  837.  
  838.         if ((AvkRet = AvkViewCleanRect(View.hView, &View.DstBox))
  839.             != OK)
  840.             return DispAvkErr(AvkRet, "AvkViewCleanRect");
  841.  
  842.         // Reset the destination of the connector to our new box.
  843.  
  844.         if ((AvkRet = AvkConnModSrcDst(View.hConnStrm2View,
  845.             NULL, &NewDstBox,
  846.           NOW)) != OK)
  847.                return DispAvkErr(AvkRet, "AvkConnModSrcDst");
  848.  
  849.         // Enable the connector.
  850.  
  851.         if ((AvkRet = AvkConnEnable(View.hConnStrm2View, NOW)) != OK)
  852.             return DispAvkErr(AvkRet, "AvkConnEnable");
  853.  
  854.     }
  855.  
  856.     // Copy the new destination coords into the view's destination box.
  857.  
  858.     COPYBOX(&View.DstBox, &NewDstBox);
  859.  
  860.     return TRUE;
  861. }
  862.  
  863. //-------------------------------------------------------------------------
  864. //FUNCTION:
  865. //
  866. //    WORD ToState(NewState)
  867. //
  868. //PARMS IN:
  869. //
  870. //    WORD    NewState;    // The new state 
  871. //
  872. //DESCRIPTION:
  873. //
  874. //    Sets a new state and enables/disables the applicable menu options.
  875. //
  876. //RETURN:
  877. //
  878. //    The old state if the state changed or remained the same.
  879. //    0xffff if the new state is an invalid value.
  880. //    
  881. //-------------------------------------------------------------------------
  882.  
  883. WORD    
  884. ToState(WORD NewState)
  885. {
  886.     WORD    OldState;
  887.  
  888.     if (NewState == ST_CAPTURING
  889.      || NewState == ST_MONITORING
  890.      || NewState == ST_INITIALIZED
  891.      || NewState == ST_UNINITIALIZED)
  892.     {
  893.         if (State != NewState)
  894.         {
  895.             OldState = State;
  896.             State = NewState;
  897.             UpdateMenus(State);
  898.             return OldState;
  899.         }
  900.         else
  901.             return NewState;
  902.     }
  903.     return 0xffff;
  904. }
  905.  
  906. //-------------------------------------------------------------------------
  907. //FUNCTION:
  908. //
  909. //    BOOL IsState(QueryState)
  910. //
  911. //PARMS IN:
  912. //
  913. //    WORD    QueryState;        a state value
  914. //
  915. //DESCRIPTION:
  916. //
  917. //    Checks whether the current state equals the caller's query state.
  918. //    
  919. //RETURN:
  920. //
  921. //    TRUE if the current state equals the caller's query state.
  922. //    FALSE if not.
  923. //
  924. //-------------------------------------------------------------------------
  925.  
  926. BOOL
  927. IsState(WORD QueryState)
  928. {
  929.     return State == QueryState;
  930. }
  931.  
  932. //-------------------------------------------------------------------------
  933. //FUNCTION:
  934. //
  935. //    WORD GetState(VOID)
  936. //
  937. //DESCRIPTION:
  938. //
  939. //    Returns the current state to the caller.
  940. //
  941. //RETURN:
  942. //
  943. //    The current value for State.
  944. //
  945. //-------------------------------------------------------------------------
  946.  
  947. WORD
  948. GetState()
  949. {
  950.     return State;
  951. }
  952.  
  953.  
  954. //-------------------------------------------------------------------------
  955. //FUNCTION:
  956. //    
  957. //    VOID SetClipTimer()
  958. //
  959. //DESCRIPTION:
  960. //    
  961. //RETURN:
  962. //     
  963. //-------------------------------------------------------------------------
  964.  
  965. VOID
  966. SetClipTimer()
  967. {
  968.     CopyList.hConn = View.hConnStrm2View;
  969.     CopyList.hwndTarget = hwndMain;
  970.     CopyList.ClipCnt = 0;
  971.  
  972.     GetClientRect(hwndMain, (LPRECT)&CopyList.rectTarget);
  973.     ClientToScreen(hwndMain, (LPPOINT)&CopyList.rectTarget);
  974.     ClientToScreen(hwndMain, (LPPOINT)&CopyList.rectTarget + 1);
  975.  
  976.     lpThunk = MakeProcInstance(ClipTimerProc, hInst);
  977.     if (SetTimer(hwndMain, CLIP_TIMER_ID, CLIP_TIMER_INTERVAL, lpThunk))
  978.         bClipTimerSet = TRUE;
  979. }
  980.  
  981. //-------------------------------------------------------------------------
  982. //FUNCTION:
  983. //    
  984. //    VOID KillClipTimer()
  985. //
  986. //DESCRIPTION:
  987. //    
  988. //RETURN:
  989. //    
  990. //-------------------------------------------------------------------------
  991.  
  992. VOID
  993. KillClipTimer()
  994. {
  995.     if (bClipTimerSet)
  996.     {
  997.         KillTimer(hwndMain, CLIP_TIMER_ID);
  998.         bClipTimerSet = FALSE;
  999.         FreeProcInstance(lpThunk);
  1000.     }
  1001. }
  1002.  
  1003. //-------------------------------------------------------------------------
  1004. //FUNCTION:                                 
  1005. //    
  1006. //    WORD FAR PASCAL TimerClipProc(hwnd, Msg, wParam, lParam)
  1007. //
  1008. //PARMS IN:
  1009. //
  1010. //    HWND    hWnd        handle to window specified in SetTimer() call.
  1011. //    WORD    Msg        always WM_TIMER
  1012. //    WORD    wParam        Timer ID
  1013. //    LONG    lParam        address of this function
  1014. //
  1015. //DESCRIPTION:
  1016. //
  1017. //
  1018. //    This function is called by the Windows timer periodically to update
  1019. //    the connector copylist.  It calls UpdateCopyList, which runs the
  1020. //    Windows Manager's list of open windows and creates a copylist 
  1021. //    to exclude all overlapping regions of our connector's destination
  1022. //    box.
  1023. //
  1024. //
  1025. //RETURN:
  1026. //
  1027. //    This function always returns 0.  The user must respond to the 
  1028. //    error message and close down the application if anything fails.
  1029. //    Note that it does turn off periodic clipping by leaving the
  1030. //    re-entry flag bInClipping set to prevent a pileup of repeated 
  1031. //    errors.
  1032. //
  1033. //-------------------------------------------------------------------------
  1034.  
  1035. WORD FAR PASCAL
  1036. ClipTimerProc(HWND hWnd, WORD Msg, WORD wParam, LONG lParam)
  1037. {
  1038.     I16            rc;
  1039.     BOOL        bStatus;
  1040.     static BOOL    bInClipping = FALSE;
  1041.  
  1042.     if (bInClipping)
  1043.         return 0;
  1044.  
  1045.     bInClipping = TRUE;
  1046.  
  1047.     rc = UpdateCopyList(&CopyList, (RECT *)&View.DstBox, View.cxView,
  1048.       View.cyView, &bStatus);
  1049.  
  1050.     switch (rc)
  1051.     {
  1052.         case AVK_ERR_OK:
  1053.             break;
  1054.  
  1055.         case COPY_ERROR:
  1056.             DispErr("ClipTimerProc", "Error in Clip2Copy");
  1057.             return 0;
  1058.  
  1059.         default:
  1060.             DispAvkErr(rc, "AvkConnCopyList");
  1061.             return 0;
  1062.     }
  1063.  
  1064.     bInClipping = FALSE;
  1065.  
  1066.     return 0;
  1067. }
  1068.  
  1069.